/****************************************************************************
File:			ED1Scene.h
Purpose:		The declaration of our ED1Scene class that will be updated
				every frame and have access to our camera, frustum, renderer,
				and future functionality. We will have only one instance of
				the class; therefore, it will be a singleton.
Author:			Kent Ward [kward@fullsail.com]
School:			Full Sail University
Last Modified:	July 22nd, 2009
*****************************************************************************/

#ifndef _ED1SCENE_H_
#define _ED1SCENE_H_

#include <vector>
#include "EDCamera.h"
#include "EDFrustum.h"
#include "EDAABB.h"
#include "EDSphere.h"
#include "Timer.h"
#include "ED1RenderObjects.h"
#include "SGKAgent.h"


class ED1Scene
{
private:

	//Constructor, Copy Constructor, Assignment Operator that will be private
	//since this is a Singleton
	ED1Scene(void) {}
	ED1Scene(const ED1Scene &) {}
	ED1Scene & operator=(const ED1Scene &) {}

public:
	~ED1Scene(void);

	/***********************************************************
	Function:		GetInstance
	Purpose:		Returns Singleton Instance of this class
	Out:
					ED1Scene&	- Our Singleton		
	Last Modified:	June 29th, 2009
	*************************************************************/
	static ED1Scene& GetInstance();

	/***********************************************************
	Function:		InitializeScene
	Purpose:		Initializes our scene by setting class 
					variables, loading assets and setting
					render states that will remain throughout
					the running of the application.
	In:
					iScreenWidth	- the width of the window
					iScreenHeight	- the height of the window
					bFullScreen		- is the window full screen
									  or not?			
	Last Modified:	June 29th, 2009
	*************************************************************/
	void InitializeScene(int iScreenWidth = 800, int iScreenHeight = 600, bool bFullScreen = true);

	/***********************************************************
	Function:		ResizeWindow
	Purpose:		Resizes our Window
	In:
					iScreenWidth	- the width of the window
					iScreenHeight	- the height of the window		
	Last Modified:	June 29th, 2009
	*************************************************************/
	void ResizeWindow(int iScreenWidth, int iScreenHeight);

	/***********************************************************
	Function:		UpdateFrame
	Purpose:		Updates our scene and all of its objects 
					based on how much time has passed since the 
					last time UpdateFrame was called
	Last Modified:	June 29th, 2009
	*************************************************************/
	void UpdateFrame();

	/***********************************************************
	Function:		Shutdown
	Purpose:		Deletes all of our Dynamic Memory
	Last Modified:	June 29th, 2009
	*************************************************************/
	void Shutdown();

	/***********************************************************
	Function:		DrawGround
	Purpose:		Draws a line grid
	Last Modified:	June 29th, 2009
	*************************************************************/
	void DrawGround(void);

	/***********************************************************
	Function:		DrawAxes
	Purpose:		Draw the OpenGL Coordinate System
	In:
					fScale	- the length of exh axis	
	Last Modified:	June 29th, 2009
	*************************************************************/
	void DrawAxes(float fScale = 1.0f);

	//Initializes our EDAppearance list. These are are also our Rendering Contexts
	void InitializeAppearances(void);
	

	//Initializes our EDRenderShapes Master List, as well as our Transparent
	//and Opaque Rendering Sets. These are our drawables.
	void InitializeRenderShapes(void);

	//TODO:
	//Clears transparent and opaque render sets
	//Updates the positions of the render shapes in the master shape list
	//frustum test with each render shape's sphere
	//	If frustum test is true, check if appearance of render shape
	//	is transparent or opaque and pass the renderset and shape into
	//	the InsertionSort function below
	void ED1Scene::UpdateSceneObjects();

	//Draw sorted Opaque Objects
	//Draw sorted Transparent objects
	void RenderSceneObjects();

	//Set render states for Opaque Rendering and draw here
	void DrawOpaqueSet( std::vector<EDRenderShape *> & RenderSet);

	//set render states for Transparent Rendering and draw here
	//Draw back face of an object first, and then the front face
	void DrawTransparentSet( std::vector<EDRenderShape *> & RenderSet);

	//It's Insertion Sort. pShape is to be insterted onto the given RenderSet. 
	//Iterate through each render shape in the set and compare distance
	//Depending on whether you are doing transparent or opaque sorting will determine
	//the sorting order. Use the stl::vector insert function to insert the shape in the 
	//appropriate shape
	bool InsertionSort(std::vector<EDRenderShape *> & RenderSet, EDRenderShape * pShape, bool bLessThan);

private:
	int m_iScreenWidth;
	int m_iScreenHeight;
	bool m_bFullScreen;

	EDCamera m_Camera;
	EDFrustum m_Frustum;

	// Let's just say our agents are here.
	std::vector<SGKAgent> m_vAgents;

	// Frame timer
	Timer m_Timer;

	//Scene Management ghettoness
	//We will have for of these, two transparent and two opaque. One of each of those will be textured.
	std::vector<EDAppearance> m_vAppearances;

	//m_vMasterShapeList
	//The Spheres in the scene. They can be in the view frustum or not. The count will be initialized 
	//to 50 but can have spheres removed or added.
	std::vector<EDRenderShape> m_vMasterShapeList;

	//m_vOpaqueRenderSet
	//A Poser RenderSet. Spheres that are opaque in appearance and have passed the view frustum test. 
	//They will be sorted prior to being rendered.
	std::vector<EDRenderShape*> m_vOpaqueRenderSet;

	//m_vTransparentSet
	//Another Poser RenderSet. Spheres that are transparent in appearance and have passed the view 
	//frustum test. They will be sorted prior to being rendered.
	std::vector<EDRenderShape*> m_vTransparentRenderSet;

public: 

	//Accessors
	bool IsFullScreen() { return m_bFullScreen; }

};

#endif